/*-*
 * FILENAME  :
 *    $HeadURL$
 *
 * STATUS  :
 *    $Revision$
 *
 *    $Author$
 *    $Date$
 *  
 *    
 * Copyright (c) 2011 Gonalge Ltda. All rights reserved.
 *
 ****************************************************************/

package org.gonalge.arbolrojonegro.negocio;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.gonalge.arbolrojonegro.dto.Nodo;

/**
 * 
 * @author Geremias Gonzalez
 */
public class Lista {

    private static final Log LOG = LogFactory.getLog(Lista.class);

    private Nodo RP = new Nodo();

    private Nodo RU = new Nodo();

    private Nodo aux;

    private Nodo vista;

    private int size;

    public Lista() {
        RP = RU = vista = null;
        size = 0;
    }

    public void insertar(int p, Object e) {
        if (size == 0) {
            aux = new Nodo();
            aux.setEleObj(e);
            RP = RU = aux;
            size++;
        } else if (p == 0) {
            aux = new Nodo();
            aux.setEleObj(e);
            aux.setRS(RP);
            RP.setRA(aux);
            RP = aux;
            size++;
        } else if (p >= size) {
            aux = new Nodo();
            aux.setEleObj(e);
            aux.setRA(RU);
            RU.setRS(aux);
            RU = aux;
            size++;
        } else if (p > 0 && p < size) {
            aux = new Nodo();
            aux.setEleObj(e);
            Nodo nodo;
            nodo = getNodo(p);
            aux.setRS(nodo);
            aux.setRA(nodo.getRA());
            (nodo.getRA()).setRS(aux);
            nodo.setRA(aux);
            size++;
        }
    }

    public void insertarConVista(Object e) {
        if (vista == null) {
            aux = new Nodo();
            aux.setEleObj(e);
            if (size == 0) {
                vista = RP = RU = aux;
                size++;
            } else {
                aux.setRA(RU);
                RU.setRS(aux);
                vista = RU = aux;
                size++;
            }
        } else {
            aux = new Nodo();
            aux.setEleObj(e);
            if (vista == RP) {
                aux.setRS(RP);
                RP.setRA(aux);
                vista = RP = aux;
                size++;
            } else if (vista == RU) {
                aux.setRA(RU);
                RU.setRS(aux);
                vista = RP = aux;
                size++;
            } else {
                aux.setRS(vista);
                aux.setRA(vista.getRA());
                vista.setRA(aux);
                aux.getRA().setRS(aux);
                vista = aux;
                size++;
            }
        }
    }

    public void eliminar(int p) {
        if (size == 1) {
            RP = RU = null;
            size = 0;
        } else if (size > 0) {
            if (p == 0) {
                RP = RP.getRS();
                RP.setRA(null);
                size--;
            }
            if (p >= size - 1) {
                RU = RU.getRA();
                RU.setRS(null);
                size--;
            }
            if (p > 0 && p < size) {
                Nodo aux1 = RP;
                while (p > 0) {
                    aux1 = aux1.getRS();
                    p--;
                }
                aux1.getRA().setRS(aux1.getRS());
                aux1.getRS().setRA(aux1.getRA());
                size--;
            }
        }
    }

    public void eliminarConVista() {
        if (vista == null) {
            if (size == 1) {
                RP = RU = null;
                size = 0;
            } else {
                RU = RU.getRA();
                RU.setRS(null);
                size--;
            }
        } else {
            if (vista == RP) {
                RP = RP.getRS();
                RP.setRA(null);
                vista = RP;
                size--;
            } else {
                if (vista == RU) {
                    RU = RU.getRA();
                    RU.setRS(null);
                    vista = RU;
                    size--;
                } else {
                    vista = vista.getRS();
                    vista.getRA().getRA().setRS(vista);
                    ;
                    vista.setRA(vista.getRA().getRA());
                    size--;
                }
            }
        }
    }

    public Nodo getNodo(int p) {
        Nodo aux1 = RP;
        while (p > 0 && aux1.getRS() != null) {
            aux1 = aux1.getRS();
            p--;
        }
        return aux1;
    }

    public Object consultar(int p) {
        Nodo aux1 = RP;
        while (p > 0) {
            aux1 = aux1.getRS();
            p--;
        }
        return aux1.getEleObj();
    }

    public void imprimir() {
        Nodo nodo = RP;
        String str = "";
        while (nodo != null) {
            str += nodo.getEle() + " ";
            nodo = nodo.getRS();
        }
        LOG.info(str.trim());
    }

    public boolean estaVacia() {
        return (RP == null && RU == null);
    }

    public boolean vistaDefinida() {
        return vista != null;
    }

    public boolean vistaPrimero() {
        boolean sw = false;
        if (!estaVacia()) {
            vista = RP;
            sw = true;
        }
        return sw;
    }

    public boolean vistaUltimo() {
        boolean sw = false;
        if (!estaVacia()) {
            vista = RU;
            sw = true;
        }
        return sw;
    }

    public boolean vistaSiguiente() {
        boolean sw = false;
        if ((!estaVacia()) && (vista.getRS() != null)) {
            vista = vista.getRS();
            sw = true;
        }
        return sw;
    }

    public boolean vistaAnterior() {
        boolean sw = false;
        if ((!estaVacia()) && (vista.getRA() != null)) {
            vista = vista.getRA();
            sw = true;
        }
        return sw;
    }

    public boolean posesionarVista(int p) {
        boolean sw = false;
        if ((!estaVacia()) && (p > 0 && p < size)) {
            vista = getNodo(p);
            sw = true;
        }
        return sw;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public int getSize() {
        return size;
    }
}
